#ifndef TESTLIBPILO_H
#define TESTLIBPILO_H

#define DEBUG_PILO_MEMORY_TCFIXEDBUFFER

#include "common/common.h"
#include "Core/TCFixedString.h"
#include "string/stringoutput.h"
#include "Core/TCFixedBuffer.h"
#include "Core/TCFixedRingBuffer.h"
#include "Core/CAtomicInteger32.h"
#include "Core/CAtomicUnsignedInteger32.h"
using namespace PILO::Core::String;



typedef INT32 (*TestCaseFunction)(void * param);


typedef struct _case_testing {
    
	INT32		ct_id;
	const char *  ct_decription;
	char *  ct_arg;
	TestCaseFunction ct_function;
	INT32 ct_result;

} case_testing_t;


inline INT32 failedOFCases(case_testing_t * casep, int_r number)
{
	INT32 cnt=0;
	for (int_r i=0; i< number; i++) {

		if (casep[i].ct_result != 0) {
			cnt ++;
		}
	}
    
	return cnt;
}

class TestElement {
public:
    TestElement() { clear();}
    TestElement(INT32 id, char * data) 
    { 
        setID(id);
        setData(data); 
    }
    ~TestElement()
    {
        setID(-1);
        memset(_data, 0xFF,sizeof(_data));
    }
    


    INT32 id() const { return _id; }
    void setID(INT32 v) { _id = v; }
    const char* data() const { return _data; }
    void setData(const char * d) { memset(_data,0,sizeof(_data)); StringCopy(_data,MCF_COUNT_OF(_data), d, MCF_COUNT_OF(_data));}
    void setData(int i)
    {
        memset(_data,0,sizeof(_data));
        FormatOutputToString(_data, sizeof(_data), "%06d", i);
    }

    
    void set(INT32 id, const char * dataTag) 
    {
        const char * tag;

        if (dataTag == MC_NULLPTR_OF_(const char *)) {

            tag = "FOX";
        } else {
            tag = dataTag;

        }

        memset(_data,0x00,sizeof(_data));

        _id = id;

        FormatOutputToString(_data, MCF_COUNT_OF(_data), "%s @ %010d",tag, id);

    }

    void clear()
    {
        _id = 0;

        memset(_data, 0x0, sizeof(_data));

    }


    BOOL operator == (const TestElement& o) const
    {
        if (this->_id != o._id) {
            return FALSE;
        }
        if ( StringCompare(this->_data, o._data, MC_INVALID_SIZE)) {
            return FALSE;
        }
        return TRUE;
    }

    BOOL operator != (const TestElement& o) const
    {
        if (this->_id != o._id) {
            return TRUE;
        }
        if ( StringCompare(this->_data, o._data, MC_INVALID_SIZE)) {
            return TRUE;
        }
        return FALSE;
    }

    BOOL operator< (const TestElement& o) const
    {
       
        if (this->_id < o._id) {
            return TRUE;
        }

        return FALSE;
    }


    void debugOutput() const
    {
        FormatOutputToConsole("@=> id=(%d) data=[%s]\n", _id, _data);
    }



private:
    INT32  _id;
    char   _data[32];

};
DECLARE_SIMPLE_TYPE(TestElement)

template<typename T>
T TMakeSampleDynamicArray(T & arrayRef, size_t numToBeFilled, const char * dataTag)
{
    char buf[32];
    const char * tag;
    if (dataTag == MC_NULLPTR_OF_(const char *)) {
        tag = "FOX";
    } else {
        tag = dataTag;
    }
    TestElement element;
    for (int i=0; i<(int) numToBeFilled; i++)
    {
        element.setID(i);

        FormatOutputToString(buf, MCF_COUNT_OF(buf), "%s @ %010d",tag, i);
        element.setData(buf);
        arrayRef.append(element);
    }

    return arrayRef;
}

template<typename T>
T TMakeSampleDynamicSortedArray(T & arrayRef, size_t numToBeFilled, const char * dataTag)
{
    const char * tag;
    if (dataTag == MC_NULLPTR_OF_(const char *)) {
        tag = "FOX";
    } else {
        tag = dataTag;
    }
    TestElement element;
    for (int i=(int)numToBeFilled-1; i>=0; i--)
    {
        element.set(i, tag);
        arrayRef.insert(element);
    }

    return arrayRef;
}

template<typename T>
void TDebugOutputArray(T & arrayRef)
{
    FormatOutputToConsole("\n");
    size_t index;
    for(index=0; index<arrayRef.size(); index++) {
        arrayRef.at(index).debugOutput();
    }
}




INT32 test_TCFixedString_Functional(INT32 id, BOOL breakOnError);
INT32 test_stringmanipulations_Functional(INT32 id, BOOL breakOnErrorOccured);
INT32 test_TCSimpleDynamicArray_Functional(INT32 id, BOOL breakOnErrorOccured);
INT32 test_TCSimpleDynamicSortedArray_Functional(INT32 id, BOOL breakOnErrorOccured);
INT32 PILOTSimpleDynamicObjectArray_FunctionalTest(INT32 id, BOOL breakOnErrorOccured);
INT32 testTCFixedBufferFunctional(INT32 id, int breakOnErrorOccured);
INT32 testTCFixedRingBufferFunctional(INT32 id, int breakOnErrorOccured);
INT32 test_CAbstractThread_Functional(INT32 id, int breakOnErrorOccured);
INT32 test_atomic_operation_functional(INT32 id, int breakOnErrorOccured);
INT32 test_atomictypes_Functional(INT32 id, int breakOnErrorOccured);
INT32 test_CThreadMutex_Functional(INT32 id, int breakOnErrorOccured);
INT32 test_CAutoMutexLocker_Functional(INT32 id, BOOL breakOnErrorOccured);

#endif /*TESTLIBPILO_H*/
